home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / misc / pdflib / p_draw.c < prev    next >
C/C++ Source or Header  |  1999-01-01  |  5KB  |  209 lines

  1. /* p_draw.c
  2.  * Copyright (C) 1997-98 Thomas Merz. All rights reserved.
  3.  *
  4.  * PDFlib drawing routines
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <math.h>
  9.  
  10. #include "p_intern.h"
  11.  
  12. /* Section 8.6.1 Path segment operators */
  13.  
  14. void
  15. PDF_moveto(PDF *p, float x, float y)
  16. {
  17.     pdf_end_text(p);
  18.     (void) fprintf(p->fp,"%s %s m\n", pdf_float(x), pdf_float(y));
  19. }
  20.  
  21. void
  22. PDF_lineto(PDF *p, float x, float y)
  23. {
  24.     pdf_end_text(p);
  25.     (void) fprintf(p->fp,"%s %s l\n", pdf_float(x), pdf_float(y));
  26. }
  27.  
  28. void
  29. PDF_curveto(PDF *p, float x1, float y1, float x2, float y2, float x3, float y3)
  30. {
  31.     pdf_end_text(p);
  32.  
  33.     if (x2 == x3 && y2 == y3)    /* second c.p. coincides with final point */
  34.     (void) fprintf(p->fp,"%s %s %s %s y\n",
  35.             pdf_float(x1), pdf_float(y1), pdf_float(x3), pdf_float(y3));
  36.     else            /* general case with four distinct points */
  37.     (void) fprintf(p->fp,"%s %s %s %s %s %s c\n",
  38.             pdf_float(x1), pdf_float(y1),
  39.             pdf_float(x2), pdf_float(y2),
  40.             pdf_float(x3), pdf_float(y3));
  41. }
  42.  
  43. /* Convenience routines */
  44.  
  45. /* 
  46.  * "Best fit" BCP approximation for an arc segment as suggested
  47.  * by Berthold K.P.Horn. Thanks BKPH!
  48.  */
  49.  
  50. #define ARC_MAGIC    0.5523
  51. #define MIN(x, y)    ((x) < (y) ? (x) : (y))
  52.  
  53. /* PDF_arc() assumes that the current point is already at the arc's start */
  54.  
  55. void
  56. PDF_arc(PDF *p, float x, float y, float r, float alpha, float beta)
  57. {
  58.     float bcp;
  59.     float cos_alpha, cos_beta, sin_alpha, sin_beta;
  60.  
  61.     if (r < 0) {
  62.     pdf_error(p, PDF_WARN, "Negative circle radius %f", r);
  63.     return;
  64.     }
  65.     
  66.     if (beta - alpha > 90.0)
  67.     {
  68.     /* cut down in 90 degree segments until done */
  69.     PDF_arc(p, x, y, r, alpha, MIN(alpha + 90, beta));
  70.     if (alpha + 90 < beta)
  71.         PDF_arc(p, x, y, r, alpha + 90, beta);
  72.     return;
  73.     }
  74.  
  75.     /* speed up special case for quadrants and circles */
  76.     if ((int) alpha == alpha && (int) beta == beta &&
  77.         beta - alpha == 90 && (int) alpha % 90 == 0)
  78.     {
  79.     /* prune angle values */
  80.     alpha = (int) alpha % 360;
  81.     beta = (int) beta % 360;
  82.  
  83.     switch ((int) alpha) {
  84.         case 0:
  85.         PDF_curveto(p, x + r, y + r*ARC_MAGIC, 
  86.             x + r*ARC_MAGIC, y + r, x, y + r);
  87.         break;
  88.         case 90:
  89.         PDF_curveto(p, x - r*ARC_MAGIC, y + r, 
  90.             x - r, y + r*ARC_MAGIC, x - r, y);
  91.         break;
  92.         case 180:
  93.         PDF_curveto(p, x - r, y - r*ARC_MAGIC, 
  94.             x - r*ARC_MAGIC, y - r, x, y - r);
  95.         break;
  96.         case 270:
  97.         PDF_curveto(p, x + r*ARC_MAGIC, y - r, 
  98.             x + r, y - r*ARC_MAGIC, x + r, y);
  99.         break;
  100.         default:
  101.         break;
  102.     }
  103.     return;
  104.     }
  105.  
  106.     alpha = alpha * M_PI / 180;        /* convert to radians */
  107.     beta = beta * M_PI / 180;        /* convert to radians */
  108.  
  109.     /* This formula yields ARC_MAGIC for alpha == 0, beta == 90 degrees */
  110.     bcp = 4/3 * (1 - cos((beta - alpha)/2)) / sin((beta - alpha)/2);
  111.     
  112.     sin_alpha = sin(alpha);
  113.     sin_beta = sin(beta);
  114.     cos_alpha = cos(alpha);
  115.     cos_beta = cos(beta);
  116.  
  117.     PDF_curveto(p, 
  118.         x + r * (cos_alpha - bcp * sin_alpha),        /* p1 */
  119.         y + r * (sin_alpha + bcp * cos_alpha),
  120.         x + r * (cos_beta + bcp * sin_beta),        /* p2 */
  121.         y + r * (sin_beta - bcp * cos_beta),
  122.         x + r * cos_beta, y + r * sin_beta);        /* p3 */
  123. }
  124.  
  125. void
  126. PDF_circle(PDF *p, float x, float y, float r)
  127. {
  128.     if (r < 0) {
  129.     pdf_error(p, PDF_WARN, "Negative circle radius %f", r);
  130.     return;
  131.     }
  132.  
  133.     /* draw four Bezier curves to approximate a circle */
  134.     PDF_moveto(p, x + r, y);
  135.     PDF_curveto(p, x + r, y + r*ARC_MAGIC, x + r*ARC_MAGIC, y + r, x, y + r);
  136.     PDF_curveto(p, x - r*ARC_MAGIC, y + r, x - r, y + r*ARC_MAGIC, x - r, y);
  137.     PDF_curveto(p, x - r, y - r*ARC_MAGIC, x - r*ARC_MAGIC, y - r, x, y - r);
  138.     PDF_curveto(p, x + r*ARC_MAGIC, y - r, x + r, y - r*ARC_MAGIC, x + r, y);
  139. }
  140.  
  141. void
  142. PDF_rect(PDF *p, float x, float y, float width, float height)
  143. {
  144.     pdf_end_text(p);
  145.     (void) fprintf(p->fp,"%s %s %s %s re\n",
  146.                 pdf_float(x), pdf_float(y),
  147.             pdf_float(width), pdf_float(height));
  148. }
  149.  
  150. void
  151. PDF_closepath(PDF *p)
  152. {
  153.     pdf_end_text(p);
  154.     (void) fputs("h\n", p->fp);
  155. }
  156.  
  157. /* Section 8.6.2 Path painting operators */
  158.  
  159. void
  160. PDF_endpath(PDF *p)
  161. {
  162.     pdf_end_text(p);
  163.     (void) fputs("n\n", p->fp);
  164. }
  165.  
  166. void
  167. PDF_stroke(PDF *p)
  168. {
  169.     pdf_end_text(p);
  170.     (void) fputs("S\n", p->fp);
  171. }
  172.  
  173. void
  174. PDF_closepath_stroke(PDF *p)
  175. {
  176.     pdf_end_text(p);
  177.     (void) fputs("s\n", p->fp);
  178. }
  179.  
  180. void
  181. PDF_fill(PDF *p)
  182. {
  183.     (void) fputs("f\n", p->fp);
  184.     pdf_end_text(p);
  185. }
  186.  
  187. void
  188. PDF_fill_stroke(PDF *p)
  189. {
  190.     pdf_end_text(p);
  191.     (void) fputs("B\n", p->fp);
  192. }
  193.  
  194. void
  195. PDF_closepath_fill_stroke(PDF *p)
  196. {
  197.     (void) fputs("b\n", p->fp);
  198.     pdf_end_text(p);
  199. }
  200.  
  201. /* Section 8.6.3 Path clipping operators */
  202.  
  203. void
  204. PDF_clip(PDF *p)
  205. {
  206.     pdf_end_text(p);
  207.     (void) fputs("W\n", p->fp);
  208. }
  209.